using System;
using System.Runtime.InteropServices;
using System.Security;
using Pinwheel.LSerialize.Debug;

namespace Pinwheel.LSerialize
{
    public static partial class Native
    {
        [SuppressUnmanagedCodeSecurity]
        public class LIBCAllocator : PInvokeAllocator
        {
            [DllImport("libc", CallingConvention = CallingConvention.Cdecl)]
            [SuppressUnmanagedCodeSecurity]
            private static extern IntPtr memset(IntPtr dest, int c, UIntPtr byteCount);

            protected sealed override unsafe void Clear(void* dest, int count)
            {
                Assert.Check(count >= 0);
                memset((IntPtr) dest, 0, (UIntPtr) (ulong) count);
            }
        }

        [SuppressUnmanagedCodeSecurity]
        public class LIBCUtility : PInvokeUtility
        {
            [DllImport("libc", CallingConvention = CallingConvention.Cdecl)]
            [SuppressUnmanagedCodeSecurity]
            private static extern IntPtr memcpy(IntPtr dest, IntPtr src, UIntPtr count);

            [DllImport("libc", CallingConvention = CallingConvention.Cdecl)]
            [SuppressUnmanagedCodeSecurity]
            private static extern IntPtr memmove(IntPtr dest, IntPtr src, UIntPtr count);

            [DllImport("libc", CallingConvention = CallingConvention.Cdecl)]
            [SuppressUnmanagedCodeSecurity]
            private static extern IntPtr memset(IntPtr dest, int c, UIntPtr byteCount);

            [DllImport("libc", CallingConvention = CallingConvention.Cdecl)]
            [SuppressUnmanagedCodeSecurity]
            private static extern int memcmp(IntPtr ptr1, IntPtr ptr2, UIntPtr byteCount);

            public sealed override unsafe void Clear(void* dest, int count)
            {
                Assert.Check(count >= 0);
                memset((IntPtr) dest, 0, (UIntPtr) (ulong) count);
            }

            public sealed override unsafe void Copy(void* dest, void* src, int count)
            {
                Assert.Check(count >= 0);
                memcpy((IntPtr) dest, (IntPtr) src, (UIntPtr) (ulong) count);
            }

            public sealed override unsafe void Move(void* dest, void* src, int count)
            {
                Assert.Check(count >= 0);
                memmove((IntPtr) dest, (IntPtr) src, (UIntPtr) (ulong) count);
            }

            public sealed override unsafe int Compare(void* ptr1, void* ptr2, int count)
            {
                Assert.Check(count >= 0);
                return memcmp((IntPtr) ptr1, (IntPtr) ptr2, (UIntPtr) (ulong) count);
            }
        }
    }
}